import os
import logging
import subprocess
import sys
from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QTabWidget, QTabBar, QMenuBar, QStatusBar, QFileDialog, QPushButton, QTextEdit, QDockWidget
from PySide6.QtGui import QAction, QIcon
from PySide6.QtCore import Qt, QTranslator, QLocale, QLibraryInfo, QRect

from src.config import app_config
from src.utils.logger import setup_logger, get_logger
from src.ui.theme import apply_theme, get_current_theme
from src.ui.tabs.generation_tab import GenerationTab
from src.ui.tabs.translation_tab import TranslationTab
from src.ui.tabs.dubbing_tab import DubbingTab
from src.ui.tabs.composition_tab import CompositionTab
from src.ui.tabs.batch_composition_tab import BatchCompositionTab
from src.ui.dialogs.settings_dialog import SettingsDialog
from src.ui.dialogs.about_dialog import AboutDialog
from src.ui.i18n import _




class MainWindow(QMainWindow):
    def __init__(self, translator):
        super().__init__()
        self.translator = translator
        self.setWindowTitle(app_config.get('app.name', "Trans Video"))
        # self.settings = QSettings(app_config.get(
        #     'app.organization_name', "baoge.org"), app_config.get('app.name', "Trans Video"))
        geometry_values = app_config.get("ui.geometry")
        if geometry_values:
            self.setGeometry(QRect(*geometry_values))

        self.qt_translator = QTranslator()
        language = app_config.get('ui.language', QLocale.system().name())
        self._setup_ui()
        self._setup_logger()
        self._load_language(language)
        self._create_menu()
        apply_theme(get_current_theme())

        self.statusBar().showMessage(_("Ready"), 3000)

        self.translator.language_changed.connect(self.retranslate_ui)
        app_config.config_saved.connect(self.on_config_saved)
        self.retranslate_ui()
        QApplication.instance().styleHints().colorSchemeChanged.connect(
            self._handle_color_scheme_change)

    def _setup_ui(self):
        self.tabs = QTabWidget()

        # Add a button to open the work directory to the right side of the tab bar
        self.open_work_dir_button = QPushButton(_("Open Work Directory"))
        self.open_work_dir_button.clicked.connect(self.open_work_directory)
        self.tabs.setCornerWidget(
            self.open_work_dir_button, Qt.Corner.TopRightCorner)

        self.generation_tab = GenerationTab()
        self.translation_tab = TranslationTab(main_window=self)
        self.dubbing_tab = DubbingTab(main_window=self)
        self.composition_tab = CompositionTab()
        self.batch_composition_tab = BatchCompositionTab()

        self.tabs.addTab(self.generation_tab, _("Subtitle Generation"))
        self.tabs.addTab(self.translation_tab, _("Subtitle Translation"))
        self.tabs.addTab(self.dubbing_tab, _("Dubbing"))
        self.tabs.addTab(self.composition_tab, _("Video Composition"))
        self.tabs.addTab(self.batch_composition_tab, _("Batch Processing"))

        self.setCentralWidget(self.tabs)
        self._create_log_dock_widget()

    def _create_menu(self):
        menu_bar = self.menuBar()

        # On macOS, the menu bar is the system menu bar by default, so we don't need to create a "File" menu.
        # On Windows/Linux, this will create a "File" menu.
        self.file_menu = menu_bar.addMenu(_("&File"))

        self.settings_action = QAction(_("&Settings..."), self)
        self.settings_action.setMenuRole(QAction.MenuRole.PreferencesRole)
        self.settings_action.triggered.connect(self.open_settings_dialog)
        self.file_menu.addAction(self.settings_action)

        self.open_work_dir_action = QAction(_("Open Work Directory"), self)
        self.open_work_dir_action.triggered.connect(self.open_work_directory)
        self.file_menu.addAction(self.open_work_dir_action)

        self.file_menu.addSeparator()

        self.exit_action = QAction(_("&Exit"), self)
        self.exit_action.setMenuRole(QAction.MenuRole.QuitRole)
        self.exit_action.triggered.connect(self.close)
        self.file_menu.addAction(self.exit_action)

        self.view_menu = menu_bar.addMenu(_("&View"))
        self.toggle_log_action = self.log_dock_widget.toggleViewAction()
        self.toggle_log_action.setText(_("&View Logs"))
        self.view_menu.addAction(self.toggle_log_action)

        self.help_menu = menu_bar.addMenu(_("&Help"))
        self.about_action = QAction(_("&About..."), self)
        self.about_action.setMenuRole(QAction.MenuRole.AboutRole)
        self.about_action.triggered.connect(self.open_about_dialog)
        self.help_menu.addAction(self.about_action)

    def _setup_logger(self):
        # This method is now responsible for connecting the UI log handler
        # The log file will be created in the project root directory.
        log_file = 'app.log'
        setup_logger(log_file, ui_callback=self.log_message)
        self.logger = get_logger(__name__)
        self.logger.info("Main window initialized")

    def log_message(self, message):
        """Receives messages from the log handler and displays them in the UI."""
        if hasattr(self, 'log_console'):
            self.log_console.append(message)
        # Only show the last line in status bar to avoid clutter
        last_line = message.strip().splitlines()[-1]
        self.statusBar().showMessage(last_line, 5000)

    def open_settings_dialog(self):
        dialog = SettingsDialog(self.translator, self)
        dialog.exec()

    def open_about_dialog(self):
        dialog = AboutDialog(self.translator, self)
        dialog.exec()

    def open_work_directory(self):
        """Opens the global workspace defined in the configuration file."""
        work_dir = app_config.get('paths.workspace', 'trans')
        if not os.path.isdir(work_dir):
            try:
                os.makedirs(work_dir, exist_ok=True)
            except OSError as e:
                self.log_message(
                    _("Could not create work directory {}: {}").format(work_dir, e))
                return

        self.open_path_in_explorer(work_dir)

    def open_path_in_explorer(self, path):
        """Opens a path in the file browser in a cross-platform way."""
        try:
            if sys.platform == "win32":
                os.startfile(path)
            elif sys.platform == "darwin":  # macOS
                subprocess.run(["open", path], check=True)
            else:  # linux
                subprocess.run(["xdg-open", path], check=True)
            self.log_message(_("Opening in file browser: {}").format(path))
        except Exception as e:
            self.log_message(
                _("Could not open directory {}: {}").format(path, e))

    def _create_log_dock_widget(self):
        self.log_dock_widget = QDockWidget(_("Logs"), self)
        self.log_dock_widget.setObjectName("LogDockWidget")
        self.log_console = QTextEdit()
        self.log_console.setReadOnly(True)
        self.log_dock_widget.setWidget(self.log_console)
        self.addDockWidget(
            Qt.DockWidgetArea.BottomDockWidgetArea, self.log_dock_widget)
        self.log_dock_widget.hide()

    def closeEvent(self, event):
        """
        Overrides the close event to ensure all background worker threads are safely terminated.
        """
        # Save window geometry
        geom = self.geometry()
        app_config.set("ui.geometry", [geom.x(), geom.y(), geom.width(), geom.height()], emit_signal=False)
        app_config.save(emit_signal=False)

        active_workers = []
        # Iterate through all tabs to find active workers
        for i in range(self.tabs.count()):
            widget = self.tabs.widget(i)
            if hasattr(widget, 'worker') and widget.worker and widget.worker.isRunning():
                self.logger.info(
                    _("Found running worker in tab: {}").format(self.tabs.tabText(i)))
                active_workers.append(widget.worker)

        if active_workers:
            self.logger.info(_("{} background tasks are running, attempting to stop...").format(
                len(active_workers)))
            self.statusBar().showMessage(_("Stopping background tasks, please wait..."), 0)

            # Request all workers to stop
            for worker in active_workers:
                worker.stop()

            # Wait for all workers to actually finish
            for worker in active_workers:
                if not worker.wait(5000):  # Wait for a maximum of 5 seconds
                    self.logger.warning(_("Worker {} did not stop within 5 seconds, may be terminated forcefully.").format(
                        type(worker).__name__))

            self.logger.info(_("All background tasks stopped."))
            self.statusBar().showMessage(_("All tasks stopped, exiting now."), 3000)

        super().closeEvent(event)

    def retranslate_ui(self):
        """
        Retranslates UI elements when the language or related configuration changes.
        """
        self.logger.debug("Retranslating UI...")

        # Update window title
        self.setWindowTitle(app_config.get('app.name', "Trans Video"))

        # Update tab titles
        self.tabs.setTabText(0, _("Subtitle Generation"))
        self.tabs.setTabText(1, _("Subtitle Translation"))
        self.tabs.setTabText(2, _("Dubbing"))
        self.tabs.setTabText(3, _("Video Composition"))
        self.tabs.setTabText(4, _("Batch Processing"))

        # Update menus
        self.file_menu.setTitle(_("&File"))
        self.settings_action.setText(_("&Settings..."))
        self.open_work_dir_action.setText(_("Open Work Directory"))
        self.exit_action.setText(_("&Exit"))
        self.view_menu.setTitle(_("&View"))
        self.toggle_log_action.setText(_("&View Logs"))
        self.help_menu.setTitle(_("&Help"))
        self.about_action.setText(_("&About..."))

        # Update buttons
        self.open_work_dir_button.setText(_("Open Work Directory"))

        # Update status bar message
        self.statusBar().showMessage(_("UI language updated"), 3000)

        self.logger.debug("UI retranslation complete.")

        # Retranslate all tabs that have a retranslate_ui method
        for i in range(self.tabs.count()):
            widget = self.tabs.widget(i)
            if hasattr(widget, 'retranslate_ui'):
                self.logger.debug(
                    _("Retranslating tab: {}").format(self.tabs.tabText(i)))
                widget.retranslate_ui()

    def _load_language(self, language):
        app = QApplication.instance()

        # Remove old translators to avoid stacking them
        app.removeTranslator(self.qt_translator)

        # Install Qt's built-in translations
        qt_path = QLibraryInfo.path(QLibraryInfo.LibraryPath.TranslationsPath)
        if self.qt_translator.load(QLocale(language), "qtbase", "_", qt_path):
            app.installTranslator(self.qt_translator)
            self.logger.info(
                _("Loaded Qt base translation: {}").format(language))
        else:
            self.logger.warning(
                _("Could not load Qt base translation: {}").format(language))


    def on_config_saved(self):
        """
        Called when the configuration is saved. Reloads necessary UI components.
        """
        self.logger.info(
            _("Configuration saved, reloading relevant UI components."))
        
        # Re-setup logger to reflect potential changes in debug level
        log_file = 'app.log'
        setup_logger(log_file, ui_callback=self.log_message)
        
        self._update_theme()

        # Reload config for all tabs that have a reload_config method
        for i in range(self.tabs.count()):
            widget = self.tabs.widget(i)
            if hasattr(widget, 'reload_config'):
                self.logger.debug(
                    _("Reloading config for tab: {}").format(self.tabs.tabText(i)))
                widget.reload_config()

    def _update_theme(self):
        """
        Update the application theme.
        """
        self.logger.debug(_("Updating theme..."))
        apply_theme(get_current_theme())
        self.logger.debug(_("Theme updated."))

    def _handle_color_scheme_change(self):
        """
        Handles the system's color scheme change signal.
        """
        current_setting = get_current_theme()
        self.logger.info(
            _("System color scheme changed. Current theme is '{}'.").format(current_setting))
        if current_setting == "auto":
            self.logger.debug(_("Auto theme is enabled, reapplying theme..."))
            apply_theme("auto")
            self.logger.debug(_("Reapplied theme based on new system setting."))
